<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
    <th:block th:include="include :: header('网站信息列表')"/>
</head>
<body class="gray-bg">
<div class="container-div">
    <div class="row">
        <div class="col-sm-12 search-collapse">
            <form id="formId">
                <div class="select-list">
                    <ul>
                        <li>
                            <label>网站名称：</label>
                            <input type="text" name="webName"/>
                        </li>
                        <li>
                            <label>网站地址：</label>
                            <input type="text" name="webAddress"/>
                        </li>
                        <li>
                            <a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i
                                    class="fa fa-search"></i>&nbsp;搜索</a>
                            <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i
                                    class="fa fa-refresh"></i>&nbsp;重置</a>
                        </li>
                    </ul>
                </div>
            </form>
        </div>

        <!-- 网站信息表格 -->
        <div class="btn-group-sm" id="toolbar" role="group">
            <a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="test:webinfo:add">
                <i class="fa fa-plus"></i> 添加
            </a>
            <a class="btn btn-primary single disabled" onclick="$.operate.edit()"
               shiro:hasPermission="test:webinfo:edit">
                <i class="fa fa-edit"></i> 修改
            </a>
            <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()"
               shiro:hasPermission="test:webinfo:remove">
                <i class="fa fa-remove"></i> 删除
            </a>
            <!--            <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="test:webinfo:export">-->
            <!--                <i class="fa fa-download"></i> 导出-->
            <!--            </a>-->
        </div>
        <div class="col-sm-12 select-table table-striped">
            <table id="bootstrap-table-webinfo"></table>
        </div>

    </div>
</div>
<th:block th:include="include :: footer"/>
<script th:inline="javascript">
    var editFlag = [[${@permission.hasPermi('test:webinfo:edit')}]];
    var testFlag = [[${@permission.hasPermi('test:webinfo:connect')}]];
    var removeFlag = [[${@permission.hasPermi('test:webinfo:remove')}]];

    var prefix = ctx + "test/webinfo";
    var prefixLog = ctx + "test/webloginfo";

    $(function () {
        // 网站信息表格配置
        var options = {
            id: 'bootstrap-table-webinfo',
            url: prefix + "/list",
            createUrl: prefix + "/add",
            updateUrl: prefix + "/edit/{id}",
            removeUrl: prefix + "/remove",
            exportUrl: prefix + "/export",
            modalName: "网站信息",
            onLoadSuccess: function(data) {
            },
            columns: [{
                checkbox: true
            },
                {
                    field: 'webId',
                    title: '网站信息序号',
                    visible: false
                },
                {
                    field: 'webName',
                    title: '网站名称'
                },
                {
                    field: 'webAddress',
                    title: '网站地址(URL)'
                },
                {
                    field: 'remark',
                    title: '备注'
                },
                {
                    field: 'result',
                    title: '测试状态',
                    formatter: function (value, row, index) {
                        if (row.result === 1) {
                            return '<span class="badge badge-primary">成功</span>';
                        } else if (row.result === 0) {
                            return '<span class="badge badge-danger">失败</span>';
                        } else if (row.result === 2) {
                            return '<span class="badge badge-secondary">未连接</span>';
                        } else {
                            return '<span class="badge badge-default">未知</span>';
                        }
                    }
                },
                {
                    title: '操作',
                    align: 'center',
                    formatter: function (value, row, index) {
                        var actions = [];
                        actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.webId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
                        actions.push('<a class="btn btn-success btn-xs ' + testFlag + '" href="javascript:void(0)" onclick="$.operate.test(\'' + row.webId + '\')" id="test-btn-' + row.webId + '"><i class="fa fa-external-link"></i>测试</a> ');
                        actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.webId + '\')"><i class="fa fa-remove"></i>删除</a>');
                        return actions.join('');
                    }
                }]
        };

        // 分别初始化两个表格
        $.table.init(options);

        /**
         * 测试网站可访问性
         * @param {string} url 要测试的URL
         * @param {number} [timeout=5000] 超时时间(ms)
         * @returns {Promise<{status: boolean, time?: number, method?: string}>}
         */
        async function testWebsiteAccessibility(url, timeout = 5000) {
            // 确保URL格式正确
            if (!url.startsWith('http://') && !url.startsWith('https://')) {
                url = 'http://' + url;
            }

            // 方法1：尝试直接fetch请求（支持CORS的网站）
            try {
                const result = await testWithFetch(url, timeout);
                if (result.status) {
                    return { ...result, method: 'fetch' };
                }
            } catch (error) {
            }

            // 方法2：尝试图片加载测试（作为fallback）
            try {
                const result = await testWithImage(url, timeout);
                return { ...result, method: 'image' };
            } catch (error) {

                return {
                    status: false,
                    error: 'all_methods_failed',
                    method: 'none'
                };
            }
        }

        /**
         * 使用fetch进行测试（移除no-cors模式）
         */
        async function testWithFetch(url, timeout) {
            const controller = new AbortController();
            const timeoutId = setTimeout(() => controller.abort(), timeout);

            try {
                const startTime = performance.now();
                const response = await fetch(url, {
                    method: 'HEAD', // 使用HEAD方法减少数据传输
                    mode: 'no-cors',
                    cache: 'no-cache'
                });
                const endTime = performance.now();
                clearTimeout(timeoutId);

                // 检查响应状态
                if (response.ok || response.status < 400) {
                    return {
                        status: true,
                        time: Math.round(endTime - startTime)
                    };
                } else {
                    return {
                        status: false,
                        error: `HTTP ${response.status}`
                    };
                }
            } catch (error) {
                clearTimeout(timeoutId);
                throw error;
            }
        }

        /**
         * 使用图片加载进行测试（fallback方法）
         */
        async function testWithImage(url, timeout) {
            return new Promise((resolve, reject) => {
                const startTime = performance.now();
                const img = new Image();
                let resolved = false;

                const cleanup = () => {
                    img.onload = null;
                    img.onerror = null;
                    img.ontimeout = null;
                };

                const timeoutId = setTimeout(() => {
                    if (!resolved) {
                        resolved = true;
                        cleanup();
                        resolve({
                            status: false,
                            error: 'timeout'
                        });
                    }
                }, timeout);

                img.onload = () => {
                    if (!resolved) {
                        resolved = true;
                        clearTimeout(timeoutId);
                        cleanup();
                        const endTime = performance.now();
                        resolve({
                            status: true,
                            time: Math.round(endTime - startTime)
                        });
                    }
                };

                img.onerror = () => {
                    if (!resolved) {
                        resolved = true;
                        clearTimeout(timeoutId);
                        cleanup();

                        // 尝试加载favicon作为最后的测试
                        testWithFavicon(url, timeout - (performance.now() - startTime))
                            .then(resolve)
                            .catch(() => resolve({
                                status: false,
                                error: 'image_load_failed'
                            }));
                    }
                };

                // 尝试加载网站的favicon
                const faviconUrl = new URL(url).origin + '/favicon.ico';
                img.src = faviconUrl;
            });
        }

        /**
         * 尝试加载favicon进行测试
         */
        async function testWithFavicon(url, remainingTimeout) {
            if (remainingTimeout <= 0) {
                throw new Error('timeout');
            }

            return new Promise((resolve, reject) => {
                const startTime = performance.now();
                const img = new Image();
                let resolved = false;

                const cleanup = () => {
                    img.onload = null;
                    img.onerror = null;
                };

                const timeoutId = setTimeout(() => {
                    if (!resolved) {
                        resolved = true;
                        cleanup();
                        reject(new Error('favicon_timeout'));
                    }
                }, remainingTimeout);

                img.onload = () => {
                    if (!resolved) {
                        resolved = true;
                        clearTimeout(timeoutId);
                        cleanup();
                        const endTime = performance.now();
                        resolve({
                            status: true,
                            time: Math.round(endTime - startTime)
                        });
                    }
                };

                img.onerror = () => {
                    if (!resolved) {
                        resolved = true;
                        clearTimeout(timeoutId);
                        cleanup();
                        reject(new Error('favicon_load_failed'));
                    }
                };

                // 尝试多个常见的favicon路径
                const baseUrl = new URL(url).origin;
                img.src = baseUrl + '/favicon.ico';
            });
        }

        // 扩展 operate 对象，添加 test 方法
        $.operate.test = function (webId) {
            // 获取表格所有数据
            var data = $('#bootstrap-table-webinfo').bootstrapTable('getData');
            var row = data.find(item => item.webId == webId);

            if (!row) {
                $.modal.alertError("未找到对应的网站信息");
                return;
            }

            // 获取网站地址
            var webAddress = row.webAddress;
            if (!webAddress) {
                $.modal.alertError("网站地址为空");
                return;
            }

            // 显示测试中提示
            $.modal.loading("正在测试网站可访问性...");

            // 获取测试按钮元素
            var testBtn = $('#test-btn-' + webId);
            var originalHtml = testBtn.html();

            // 更改按钮为加载状态
            testBtn.html('<i class="fa fa-spinner fa-spin"></i> 测试中...');
            testBtn.removeClass('btn-success').addClass('btn-warning');
            testBtn.prop('disabled', true);


            // 执行测试
            testWebsiteAccessibility(webAddress, 5000)
                .then(result => {

                    $.modal.closeLoading();

                    if (result.status) {
                        // 构建成功消息，包含测试方法信息
                        let successMsg = `网站访问测试成功，耗时${result.time}ms`;
                        if (result.method) {
                            const methodNames = {
                                'fetch': '直接连接',
                                'image': '图片加载',
                                'none': '所有方法'
                            };
                            successMsg += ` (${methodNames[result.method] || result.method})`;
                        }

                        $.modal.alertSuccess(successMsg);

                        // 测试成功，显示成功图标
                        testBtn.html('<i class="fa fa-check"></i> 成功');
                        testBtn.removeClass('btn-warning').addClass('btn-success');

                        // 延迟恢复原状态
                        setTimeout(function() {
                            testBtn.html(originalHtml);
                            testBtn.prop('disabled', false);
                        }, 2000);

                        // 测试成功，保存记录到数据库
                        saveTestResult(row, true, result.time, null);

                    } else {
                        // 测试失败，显示失败图标
                        testBtn.html('<i class="fa fa-times"></i> 失败');
                        testBtn.removeClass('btn-warning').addClass('btn-danger');

                        // 延迟恢复原状态
                        setTimeout(function() {
                            testBtn.html(originalHtml);
                            testBtn.prop('disabled', false);
                        }, 2000);

                        // 根据错误类型显示不同的错误消息
                        if (result.error === 'timeout') {
                            $.modal.alertError("网站访问超时（5秒内无响应）");
                            saveTestResult(row, false, null, 'timeout');
                        } else if (result.error === 'all_methods_failed') {
                            $.modal.alertError("网站无法访问：所有测试方法均失败，网站可能不存在或无法连接");
                            saveTestResult(row, false, null, 'all_methods_failed');
                        } else if (result.error && result.error.startsWith('HTTP ')) {
                            $.modal.alertError(`网站返回错误状态：${result.error}`);
                            saveTestResult(row, false, null, 'http_error');
                        } else {
                            $.modal.alertError("网站无法访问，请检查网址是否正确");
                            saveTestResult(row, false, null, 'network_error');
                        }
                    }

                    // 刷新整个表格以更新状态显示
                    $('#bootstrap-table-webinfo').bootstrapTable('refresh');
                })
                .catch(error => {
                    $.modal.closeLoading();
                    // 出现异常，显示失败图标
                    testBtn.html('<i class="fa fa-times"></i> 错误');
                    testBtn.removeClass('btn-warning').addClass('btn-danger');

                    // 延迟恢复原状态
                    setTimeout(function() {
                        testBtn.html(originalHtml);
                        testBtn.prop('disabled', false);
                    }, 2000);
                    $.modal.alertError("测试过程中发生错误：" + error.message);

                    // 刷新整个表格以更新状态显示
                    $('#bootstrap-table-webinfo').bootstrapTable('refresh');
                });
        };

        // 保存测试结果到数据库
        function saveTestResult(row, isSuccess, responseTime, errorType) {
            // 显示保存中提示
            $.modal.loading("正在保存测试结果...");

            // 构造测试结果描述
            let testDescription = "";
            if (isSuccess) {
                testDescription = `网站可访问性测试成功，响应时间: ${responseTime}ms`;
            } else if (errorType === 'timeout') {
                testDescription = "网站可访问性测试失败：连接超时（5秒内无响应）";
            } else {
                testDescription = "网站可访问性测试失败：网络连接错误";
            }

            // 构造要保存的数据
            var testData = {
                webId: row.webId,
                result: isSuccess?1:0,
                deptId: row.deptId,
                userId: row.userId,
                remark: testDescription
            };

            // 调用后端新增接口保存测试记录
            $.ajax({
                url: prefixLog + "/add",
                type: "post",
                dataType: "json",
                data: testData,
                success: function (result) {
                    $.modal.closeLoading();
                    if (result.code == web_status.SUCCESS) {
                        // 刷新日志表格数据
                        $.tableLog.refresh();
                    }
                },
                error: function () {
                    $.modal.closeLoading();

                }
            });
        }
    });
</script>
</body>
</html>
